﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
/*
 * 根据cpp ctp的两个头文件生成cs对应的struct类型
 * 注意更改输入输出地址        
 * string typedefAddr = @"C:\CTP_CSHARP\CTP_V636_20141230_win32\ThostFtdcUserApiDataType.h";
 * string cppStructAddr = @"C:\CTP_CSHARP\CTP_V636_20141230_win32\ThostFtdcUserApiStruct.h";
 * string outputAddr = @"D:\CSCTP.txt";
 */

namespace translateCTPStruct
{
    class Program
    {
        static void Main(string[] args)
        {
            string typedefAddr = @"C:\CTP_CSHARP\CTP_V636_20141230_win32\ThostFtdcUserApiDataType.h";
            string cppStructAddr = @"C:\CTP_CSHARP\CTP_V636_20141230_win32\ThostFtdcUserApiStruct.h";
            string outputAddr = @"D:\CSCTP.txt";

            StreamReader objReader = new StreamReader(typedefAddr);
            string sLine = "";

            //读取所有数据类型
            //alltypes 存储所有转换对应关系
            Dictionary<String, String> allTypes = new Dictionary<String, String>();
            while (sLine != null)
            {
                sLine = objReader.ReadLine();
                if (sLine != null && sLine.Contains("typedef"))
                {
                    if (sLine.Contains("["))
                    {
                        //char[]
                        string[] tempArray = sLine.Split(' ');
                        sLine = tempArray[2];
                        int begIndex = sLine.IndexOf('[');
                        int endIndex = sLine.IndexOf(']');

                        string key = sLine.Substring(0, begIndex);
                        string value = "char" + sLine.Substring(begIndex + 1, endIndex - begIndex - 1);
                        //Console.WriteLine(key);
                        if (allTypes.ContainsKey(key))
                        {
                            continue;
                        }
                        else
                        {
                            allTypes.Add(key, value);
                        }
                    }
                    else
                    {
                        //其他类型
                        string[] tempArray = sLine.Split(' ');
                        allTypes.Add(tempArray[2].Replace(";", ""), tempArray[1]);
                    }
                }
            }
            objReader.Close();

            //读取所有cpp 的文件
            StreamReader objReader1 = new StreamReader(cppStructAddr, UnicodeEncoding.GetEncoding("GB2312"));
            ArrayList lines = new ArrayList();
            sLine = "";
            while (sLine != null)
            {
                sLine = objReader1.ReadLine();
                if (sLine != null && !sLine.Contains("#"))
                {
                    lines.Add(sLine);
                }
            }
            objReader1.Close();


            Console.ReadKey();

            //开始对文件进行编辑
            int i = 0;
            while (i < lines.Count)
            {
                sLine = lines[i].ToString();
                //处理struct
                if (sLine.Contains("struct"))
                {
                    lines[i] = "public " + sLine;
                    lines.Insert(i, "[StructLayout(LayoutKind.Sequential)]");
                    i = i + 1;
                }
                //处理花括号
                if (sLine.Contains("{") || sLine.Contains("}"))
                {
                    i++;
                    continue;
                }
                //处理实际语句
                if (sLine.Contains(";"))
                {
                    string temp = sLine.Trim();
                    string[] tempStr = temp.Split('\t');
                    string part1 = tempStr[0];
                    string part2 = tempStr[1];

                    if (allTypes.ContainsKey(part1))
                    {
                        string csType = allTypes[part1];
                        //找到对应类型后开始转换
                        if (csType.Contains("char") && csType.Length > 4)
                        {
                            //处理字符串情况
                            csType = csType.Replace("char", "");
                            sLine = "\t[MarshalAs(UnmanagedType.ByValTStr, SizeConst = " + csType + ")] public string" + "\t" + part2;

                        }
                        else
                        {
                            //处理非字符串情况
                            sLine = "\tpublic " + csType + "\t" + part2;
                        }

                    }
                    else
                    {
                        //如果没有找到对应key 说明有问题
                        sLine = "TYPE NOT FOUND!";
                    }

                    //Console.WriteLine(part1);
                    lines[i] = sLine;
                }
                i++;


            }

            //将文件导出到txt
            FileStream fs = new FileStream(outputAddr, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs);
            foreach (string a in lines)
            {
                sw.WriteLine(a);
            }
            sw.Flush();
            sw.Close();
            fs.Close();
        }
    }
}
